package com.sx.medicinecard.task;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AgreementParams;
import com.alipay.api.domain.AlipayTradePayModel;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.response.AlipayTradePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sx.medicinecard.common.MyThreadPoolSingleton;
import com.sx.medicinecard.entity.*;
import com.sx.medicinecard.mapper.SxAliAccountInfoMapper;
import com.sx.medicinecard.mapper.SxOrderInfoBrushMapper;
import com.sx.medicinecard.mapper.SxSignContractBrushMapper;
import com.sx.medicinecard.service.SxSignContractBrushService;
import com.sx.medicinecard.utils.DateUtils;
import com.sx.medicinecard.utils.SnowflakeIdUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;


/**
 * 刷单定时任务
 */

@Configuration
@EnableScheduling
@Slf4j
public class BrushTask {

    @Resource
    private SxSignContractBrushMapper sxSignContractBrushMapper;

    @Resource
    private SxAliAccountInfoMapper sxAliAccountInfoMapper;

    @Resource
    private SxOrderInfoBrushMapper sxOrderInfoBrushMapper;

    @Resource
    private SxSignContractBrushService sxSignContractBrushService;

    private Boolean run = true;

    //每天4点自动扣费（刷单）
//    @Scheduled(cron = "0 0 4 * * *") // 每天晚上23点59分执行
    public void automaticUpdateVip() {
        if(!run){
            return;
        }
        log.info("执行定时自动扣费（刷单）任务");

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        //获取五天
        //查询询签约表，下次扣款时间为5天内的用户
        Date startTime = DateUtil.beginOfDay(new Date());  //今天开始时间
        Date endTime = DateUtil.endOfDay(DateUtils.dateAfterDay(new Date(), 4));
        //5天后时间
        LambdaQueryWrapper<SxSignContractBrush> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(SxSignContractBrush::getIsSignType, "1");
        wrapper.between(SxSignContractBrush::getNextDeductDate, startTime, endTime);
        wrapper.orderByAsc(SxSignContractBrush::getNextDeductDate);
        List<SxSignContractBrush> sxSignContractBrushList = sxSignContractBrushMapper.selectList(wrapper);

        if (ObjectUtil.isEmpty(sxSignContractBrushList)) {
            log.error("未查询到需要自动扣款(刷单)的账户");
            return;
        }
        ExecutorService executorService = MyThreadPoolSingleton.getInstance();
        for (SxSignContractBrush sxSignContractBrush : sxSignContractBrushList) {
            executorService.submit(() -> {
                try {
                    Date nowDate = new Date();
                    //调用支付宝接口自动扣费
                    //根据签约对象获取支付宝账户id，查询支付宝账户信息
                    List<SxAliAccountInfo> accountStatusList = sxAliAccountInfoMapper.selectList(Wrappers.lambdaQuery(SxAliAccountInfo.class).eq(SxAliAccountInfo::getAliAccountId, sxSignContractBrush.getAliAccountId()));
                    if (accountStatusList.isEmpty()) {
                        log.error("没有可用的(刷单)支付宝账户，请联系管理员！");
                        return;
                    }
                    SxAliAccountInfo sxAliAccountInfo = accountStatusList.get(0);

                    //调用支付宝支付
                    AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig(sxAliAccountInfo));

                    // 构造请求参数以调用接口
                    AlipayTradePayRequest requestPay = new AlipayTradePayRequest();
                    AlipayTradePayModel model = new AlipayTradePayModel();

                    // 设置商户订单号
                    String yuankeOrderNo = String.valueOf(SnowflakeIdUtils.generateId());
                    model.setOutTradeNo(yuankeOrderNo);
                    // 设置订单总金额
                    //刷单价格
                    model.setTotalAmount(String.valueOf(sxAliAccountInfo.getBrushAmount()));
                    // 设置订单标题
                    model.setSubject(sxAliAccountInfo.getSubject()); //从支付宝账户信息获取
                    // 设置代扣信息
                    AgreementParams agreementParams = new AgreementParams();
                    agreementParams.setAgreementNo(sxSignContractBrush.getSignSerialNumber());  //签约流水号
                    model.setAgreementParams(agreementParams);
                    // 设置产品码
                    model.setProductCode(sxAliAccountInfo.getProductCode());  //GENERAL_WITHHOLDING

                    requestPay.setBizModel(model);
                    requestPay.putOtherTextParam("app_auth_token", sxAliAccountInfo.getAppAuthToken());    //从支付宝账户获取

                    AlipayTradePayResponse response = alipayClient.execute(requestPay);
                    if (response.isSuccess()) {
                        log.info("支付宝(刷单)支付接口调用成功！");
                        //通知下游
                        JSONObject responseData = JSONObject.parseObject(response.getBody());
                        log.info("(刷单)支付返回参数->" + responseData.toString());

                        Date nextDeductDate = DateUtils.dateAfterDay(sxSignContractBrush.getNextDeductDate(), sxAliAccountInfo.getDeductCycle());
                        sxSignContractBrush.setNextDeductDate(nextDeductDate);      //下次扣款时间
                        sxSignContractBrush.setUpdateTime(nowDate);
                        log.info("自动续费(刷单)成功后，更新下次退款时间");
                        sxSignContractBrushMapper.updateById(sxSignContractBrush);

                        //创建(刷单)订单
                        JSONObject payData = JSONObject.parseObject(responseData.get("alipay_trade_pay_response").toString());
                        sxSignContractBrushService.createOrderBrush(sxSignContractBrush,yuankeOrderNo,"",payData);

                    }else {
                        log.error("支付宝(刷单)支付接口调用失败！");
                        //如果签约表中下次扣费时间为今天，扣费失败后更新签约表中下次扣款时间 并更改支付宝周期性扣款协议
                        String nextDeductTime = sdf.format(sxSignContractBrush.getNextDeductDate());
                        if (sdf.format(new Date()).equals(nextDeductTime)) {
                            LocalDate nextDeductDate = LocalDate.parse(nextDeductTime).plusDays(sxAliAccountInfo.getDelayDay());
                            Date deductTime = DateUtils.localDateToDate(nextDeductDate);
                            sxSignContractBrush.setLastDeductTime(nowDate);
                            sxSignContractBrush.setNextDeductDate(deductTime);
                            sxSignContractBrush.setUpdateTime(nowDate);
                            sxSignContractBrushMapper.updateById(sxSignContractBrush);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        log.info("执行自动扣费（刷单）成功");
    }



    //每天定时执行刷单解约
    @Scheduled(cron = "0 0 1 * * *")
    public void cancelSigmBrush() {
        if(!run){
            return;
        }
        log.info("执行定时刷单解约任务");
        
        //查询出所有已签约用户
        List<SxSignContractBrush> sxSignContractBrushList = sxSignContractBrushMapper.selectList(new QueryWrapper<SxSignContractBrush>().eq("is_sign_type", "1"));

        for(SxSignContractBrush sxSignContractBrush : sxSignContractBrushList){
            sxSignContractBrushService.unSign(sxSignContractBrush.getPhoneNo());
        }
        log.info("执行定时刷单解约任务完成，一共解约{}笔",sxSignContractBrushList.size());

    }



    private static AlipayConfig getAlipayConfig(SxAliAccountInfo sxAliAccountInfo) {
        String privateKey = sxAliAccountInfo.getPrivateKey();
        String alipayPublicKey = sxAliAccountInfo.getAlipayPublicKey();
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
        alipayConfig.setAppId(sxAliAccountInfo.getAppId());
        alipayConfig.setPrivateKey(privateKey);
        alipayConfig.setFormat("json");
        alipayConfig.setAlipayPublicKey(alipayPublicKey);
        alipayConfig.setCharset("UTF-8");
        alipayConfig.setSignType("RSA2");
        return alipayConfig;
    }

}
